﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;

namespace IoTCM
{
    class SampleThingProvider : IThingProvider
    {
        private Thing m_bus;
        private Timer m_simulationTimer;

        private Dictionary<string, object> m_values;

        public SampleThingProvider()
        {
            m_bus = new Thing("vehicle_1", "1", "vehicle", "Bus",
                    new Thing("engine", "2", StandardThing.Engine, "Vehicle Engine",
                        new DataItem("engine.temperature", StandardType.Decimal, StandardData.Temperature, StandardUnit.Celsius, false),
                        new DataItem("engine.rpm", StandardType.Integer, StandardData.RPM, StandardUnit.None, false),
                        new DataItem("engine.running", StandardType.Boolean, StandardData.OnOff, StandardUnit.None, false),
                        new DataItem("engine.oil_pressure", StandardType.Decimal, StandardData.Pressure, StandardUnit.Pascal, false)
                        ),
                    new Thing("brakes", "3", "brakes", "Vehicle Brakes",
                        new DataItem("brake.temperature", StandardType.Decimal, StandardData.Temperature, StandardUnit.Celsius, false)
                        ));

            m_values = new Dictionary<string, object>();

            BuildValueDictionary();

            // start simulating data
            m_simulationTimer = new Timer(SimulationTimerProc, null, 1000, Timeout.Infinite);
        }

        private void BuildValueDictionary()
        {
            // TODO: maybe build this up dynamically?
            m_values.Add("engine.temperature", 0);
            m_values.Add("engine.rpm", 0);
            m_values.Add("engine.running", false);
            m_values.Add("engine.oil_pressure", 0);

            m_values.Add("brake.temperature", 0);
        }

        public Thing GetThings()
        {
            return m_bus;
        }

        public Thing GetThings(string thingID)
        {
            if (string.Compare(m_bus.ID, thingID, true) == 0) return m_bus;

            return m_bus.Things.Find(thingID);
        }

        public bool ContainsValueID(string valueID)
        {
            return m_values.ContainsKey(valueID);
        }

        public DataValueCollection GetValues()
        {
            var list = new DataValueCollection(m_bus.Instance, DateTime.Now);

            foreach (var value in m_values)
            {
                list.Add(GetCurrentValue(value.Key));
            }

            return list;
        }

        public DataValueCollection GetValues(string thingID)
        {
            var thing = m_bus.Things.Find(thingID);

            if (thing == null) return GetValue(thingID);

            var list = new DataValueCollection(thing.Instance, DateTime.Now);

            foreach (var item in thing.Items)
            {
                if (m_values.ContainsKey(item.ID))
                {
                    list.Add(GetCurrentValue(item.ID));
                }
            }

            return list;
        }

        public DataValueCollection GetValue(string valueID)
        {
            string instance;

            var item = m_bus.Items[valueID];

            if (item == null)
            {
                var container = m_bus.Things.FindValueContainer(valueID);
                if (container == null)
                {
                    return null;
                }

                instance = container.Instance;
            }
            else
            {
                instance = m_bus.Instance;
            }

            var list = new DataValueCollection(instance, DateTime.Now);
            list.Add(GetCurrentValue(valueID));

            return list;
        }

        public DataValue GetCurrentValue(string valueID)
        {
            if (!m_values.ContainsKey(valueID))
            {
                throw new ArgumentException(string.Format("No value found with ID '{0}'", valueID));
            }

            return new DataValue()
            {
                ID = valueID,
                Value = m_values[valueID]
            };

        }
        public void UpdateCurrentValues(IEnumerable<DataValue> values)
        {
            foreach(var v in values)
            {
                Debug.WriteLine(string.Format("{0}={1}", v.ID, v.Value));
            }
        }

        private void SimulationTimerProc(object state)
        {
            m_values["engine.rpm"] = Convert.ToInt32(m_values["engine.rpm"]) + 100;

            // re-start the timer
            m_simulationTimer.Change(1000, Timeout.Infinite);
        }
    }
}

